// #include "BlockQueue.hpp"
// #include "Thread.hpp"
// // #include "Task.hpp"
// #include <string>
// #include <vector>
// #include <unistd.h>
// #include <ctime>

// using namespace ThreadModule;
// int a = 10;
// using blockqueue_t = BlockQueue<Task>;

// void PrintHello()
// {
//     std::cout << "hello world" << std::endl;
// }
// // class ThreadData
// // {
// // private:
// //     blockqueue_t &bq;
// //     std::string who;
// // };


// void Consumer(blockqueue_t &bq)
// {
//     while (true)
//     {
//         // 1. 从blockqueue取下来任务
//         Task t;
//         bq.Pop(&t);
//         // 2. 处理这个任务
//         t(); //消费者私有
//         // std::cout << "Consumer Consum data is : " << t.ResultToString() << std::endl;
//     }
// }

// void Productor(blockqueue_t &bq)
// {
//     srand(time(nullptr)^pthread_self());
//     int cnt = 10;
//     while (true)
//     {
//         sleep(1);
//         // // 1. 获取任务
//         // int a = rand() % 10 + 1;
//         // usleep(1234);
//         // int b = rand() % 20 + 1;
//         // Task t(a, b);
//         // 2. 把获取的任务，放入blockqueue
//         Task t = PrintHello;
//         bq.Enqueue(t);
//         // std::cout << "Productor product data is : " << t.DebugToString() << std::endl;
//     }
// }

// void StartComm(std::vector<Thread<blockqueue_t>> *threads, int num, blockqueue_t &bq, func_t<blockqueue_t> func)
// {
//     for (int i = 0; i < num; i++)
//     {
//         std::string name = "thread-" + std::to_string(i + 1);
//         threads->emplace_back(func, bq, name);
//         threads->back().Start();//创建线程：执行函数Consumer/Productor，传递：参数阻塞队列结构体指针，
//     }
// }

// void StartConsumer(std::vector<Thread<blockqueue_t>> *threads, int num, blockqueue_t &bq)
// {
//     StartComm(threads, num, bq, Consumer);
// }

// void StartProductor(std::vector<Thread<blockqueue_t>> *threads, int num, blockqueue_t &bq)
// {
//     StartComm(threads, num, bq, Productor);
// }

// void WaitAllThread(std::vector<Thread<blockqueue_t>> &threads)
// {
//     for (auto &thread : threads)
//     {
//         thread.Join();
//     }
// }

// int main()
// {
//     blockqueue_t *bq = new blockqueue_t(5);//阻塞队列结构体指针
//     std::vector<Thread<blockqueue_t>> threads;//线程池，将阻塞队列传递给每一个线程执行执行函数
//     // std::vector<Thread<ThreadData>> threads;

//     StartConsumer(&threads, 3, *bq);//*bq是结构体
//     StartProductor(&threads, 1, *bq);
//     WaitAllThread(threads);

//     return 0;
// }

















































// #include <iostream>
// #include <string>
// #include <vector>
// #include <pthread.h>
// #include <unistd.h>

// pthread_cond_t gcond = PTHREAD_COND_INITIALIZER; // 条件变量
// pthread_mutex_t gmutex = PTHREAD_MUTEX_INITIALIZER; // 互斥锁

// void *SlaverCore(void *args)//副线程执行函数，重入 函数，副线程都执行此函数
// {
//     std::string name = static_cast<const char *>(args);
//     while (true)
//     {
//         // 1. 加锁
//         pthread_mutex_lock(&gmutex);
//         // 2. 一般条件变量是在加锁和解锁之间使用的
//         pthread_cond_wait(&gcond, &gmutex); // gmutex:这个是，是用来被释放的[前一半],所有线程都会入等待队列，解锁，其他线程入等待队列---加锁，出等待队列
//         std::cout << "当前被叫醒的线程是: " << name << std::endl;
//         // 3. 解锁
//         pthread_mutex_unlock(&gmutex);
//     }
// }

// void *MasterCore(void *args)//主线程执行函数
// {
//     sleep(3);
//     std::cout << "master 开始工作..." << std::endl;
//     std::string name = static_cast<const char *>(args);
//     while (true)
//     {
//         // pthread_cond_signal(&gcond);// 唤醒其中一个队列首部的线程
//         pthread_cond_broadcast(&gcond);// 唤醒队列中所有的线程
//         std::cout << "master 唤醒一个线程..." << std::endl;
//         sleep(1);
//     }
// }

// void StartMaster(std::vector<pthread_t> *tidsptr)
// {
//     pthread_t tid;
//     int n = pthread_create(&tid, nullptr, MasterCore, (void *)"Master Thread");//创建主线程
//     if (n == 0)
//     {
//         std::cout << "create master success" << std::endl;
//     }
//     tidsptr->emplace_back(tid);//将主线程ID入队列
// }

// void StartSlaver(std::vector<pthread_t> *tidsptr, int threadnum = 3)
// {
//     for (int i = 0; i < threadnum; i++)
//     {
//         char *name = new char[64];
//         snprintf(name, 64, "slaver-%d", i + 1); // thread-1
//         pthread_t tid;
//         int n = pthread_create(&tid, nullptr, SlaverCore, name);//创建副线程
//         if (n == 0)
//         {
//             std::cout << "create success: " << name << std::endl;
//             tidsptr->emplace_back(tid);//奴隶线程ID入队列
//         }
//     }
// }

// void WaitThread(std::vector<pthread_t> &tids)
// {
//     for (auto &tid : tids)
//     {
//         pthread_join(tid, nullptr);
//     }
// }

// int main()
// {
//     std::vector<pthread_t> tids;//存放线程的ID、目的是等待线程释放资源
//     StartMaster(&tids);
//     StartSlaver(&tids, 5);
//     WaitThread(tids);
//     return 0;
// }



























// #include <iostream>
// #include <vector>
// #include <mutex>
// // #include "LockGuard.hpp"
// #include "Thread.hpp"

// using namespace ThreadModule;

// #ifndef __LOCK_GUARD_HPP__
// #define __LOCK_GUARD_HPP__

// #include <iostream>
// #include <pthread.h>

// class LockGuard
// {
// public:
//     LockGuard(pthread_mutex_t *mutex):_mutex(mutex)//用一把锁来初始化lockguard
//     {
//         pthread_mutex_lock(_mutex); // 构造加锁
//     }
//     ~LockGuard()
//     {
//         pthread_mutex_unlock(_mutex);
//     }
// private:
//     pthread_mutex_t *_mutex;
// };

// #endif
// class ThreadData
// {
// public:
//     ThreadData(int &tickets, const std::string &name)
//         : _tickets(tickets), _name(name), _total(0)
//     {
//     }
//     ~ThreadData()
//     {
//     }

// public:
//     int &_tickets;      //所有的线程，最后都会引用同一个全局的g_tickets，总票数
//     std::string _name;  //线程名字
//     int _total;         //此线程抢到的票数
//     // std::mutex &_mutex; //锁
// };

// // pthread_mutex_t gmutex = PTHREAD_MUTEX_INITIALIZER;

// //数据不一致
// int g_tickets = 10000; // 共享资源，没有保护的, 临界资源

// void route(ThreadData *td)//执行函数，每一个线程都拿到时同一个指针，指向同一个空间
// {
//     // 加锁
//     while (true)
//     {
//         // 访问临界资源的代码，叫做临界区！--- 我们加锁，本质就是把并行执行 --- 串行执行 --- 加锁的粒度要约细越好
//         // pthread_mutex_lock(&gmutex); // 加锁 : 竞争锁是自由竞争的，竞争锁的能力太强的线程，会导致其他线程抢不到锁 --- 造成了其他线程的饥饿问题！
//         //pthread_mutex_lock(&td->_mutex);
//         if (td->_tickets > 0)        // 1
//         {
//             // 模拟一次抢票的逻辑
//             usleep(1000);//等待
//             printf("%s running, get tickets: %d\n", td->_name.c_str(), td->_tickets); // 2
//             td->_tickets--;                                                           // 3
//             //pthread_mutex_unlock(&td->_mutex); // 解锁
//             td->_total++;
//         }
//         else
//         {
//             //pthread_mutex_unlock(&td->_mutex); // 解锁
//             break;
//         }
//     }
//     // 解锁
// }

// // void route(ThreadData *td)
// // {
// //     while (true)
// //     {
// //         { // 担心就用这个
// //             LockGuard guard(&td->_mutex); // 临时对象， RAII风格的加锁和解锁
// //             // td->_mutex.lock();
// //             // std::lock_guard<std::mutex> lock(td->_mutex);
// //             if (td->_tickets > 0) // 1
// //             {
// //                 usleep(1000);
// //                 printf("%s running, get tickets: %d\n", td->_name.c_str(), td->_tickets); // 2
// //                 td->_tickets--;                                                           // 3
// //                 td->_total++;
// //                 // td->_mutex.unlock();
// //             }
// //             else
// //             {
// //                 // td->_mutex.unlock();
// //                 break;
// //             }
// //         }
// //     }
// // }

// const int num = 4;
// int main()
// {
//     // std::cout << "main： &tickets: " << &g_tickets << std::endl;
//     // pthread_mutex_t mutex;
//     // pthread_mutex_init(&mutex, nullptr);
//     // std::mutex mutex;

//     std::vector<Thread<ThreadData *>> threads;
//     std::vector<ThreadData *> datas;
//     // 1. 创建一批线程
//     for (int i = 0; i < num; i++)
//     {
//         std::string name = "thread-" + std::to_string(i + 1);
//         ThreadData *td = new ThreadData(g_tickets, name);//构造一个ThreadData指针td
//         threads.emplace_back(route, td, name);//将td作为线程执行函数参数传递给每一个线程
//         datas.emplace_back(td);//保存ThreadData指针td
//     }

//     // 2. 启动 一批线程
//     for (auto &thread : threads)
//     {
//         thread.Start();
//     }

//     // 3. 等待一批线程
//     for (auto &thread : threads)
//     {
//         thread.Join();
//         // std::cout << "wait thread done, thread is: " << thread.name() << std::endl;
//     }
//     sleep(1);
//     // 4. 输出统计数据
//     for (auto data : datas)
//     {
//         std::cout << data->_name << " : " << data->_total << std::endl;
//         delete data;
//     }

//     // pthread_mutex_destroy(&mutex);
//     return 0;
// }
